/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#pragma once

#include "引擎枚举数据.h"

#include <几何计算.h>

#include "面/面.h"
#include "材质/资产.h"
#include "纹理/纹理.h"
#include "UI主题.h"
#include "Input/Input.h"
#include "core/属性.h"


#include <map>
#include <unordered_set>
#include <deque>
#include <stack>



#define DEF_拖放状态_结束拖放	0
#define DEF_拖放状态_准备		1
#define DEF_拖放状态_开始拖放	2
#define DEF_拖放状态_拖放		3



#define DEF_WIDGET_根布局 "widgetType_根布局"
#define DEF_WIDGET_对话框 "widgetType_对话框"




typedef struct {
	uint16 id_变换;
	uint16 id_颜色;
	uint16 id_元素;
	uint16 id_图元;

	uint16 id_线属性;
}S_单色绘制ID;

typedef struct {
	uint16 id_变换;
	uint16 id_边颜色;
	uint16 id_面颜色;
	uint16 id_边元素;
	uint16 id_面元素;
	uint16 id_图元;
}S_单色边面ID;

/*typedef struct {
	uint16 id_变换;
	uint16 id_颜色;
	uint16 id_元素;
	uint16 id_图元;
}S_纹理面绘制ID;*/

typedef struct {
	S_2D笔刷	笔刷;
	//S_Font		文字tex;
	uint16		id_变换;
	uint16		id_颜色;
	uint16		id_元素;
	//和 S_2D文本对象 文本ID 是同一个
	uint16		id_文本;
}S_单色文本绘制ID;

typedef struct {
	S_GPU内存块 id_变换;
	S_GPU内存块 id_颜色;
	S_GPU内存块 id_文本;
	uint16          层ID;
}S_行文本绘制ID;

typedef struct {
	S_GPU内存块 id_变换;
	S_GPU内存块 id_颜色;
	uint16          层ID;
}S_图标绘制ID;

typedef struct {
	ivec2 开始行列;
	ivec2 结束行列;
}S_文本选框区域ID;

typedef struct {
	wchar_t 前;
	wchar_t 后;
}S_文本前后;




typedef void(*fp_Widget布局)(struct C_Widget* r, struct C_Widget** w, uint32 num);

typedef E_事件是否传递(*fp_Widget鼠标按键)(struct C_Widget* self, const E_鼠标按钮& 按钮);
typedef E_事件是否传递(*fp_Widget鼠标移动)(struct C_Widget* self, const ivec4& value);
typedef E_事件是否传递(*fp_Widget鼠标)(struct C_Widget* self, const S_鼠标& 鼠标);
typedef E_事件是否传递(*fp_Widget按键按下)(struct C_Widget* self, const S_键盘& ks);

typedef void(*fp_Widget绘制)(struct C_Widget* self, struct S_2D画布* 画布);
typedef void(*fp_Widget动画)(struct C_Widget* self);
typedef void(*fp_Widget更新)(struct C_Widget* self);


typedef bool(*fp_Widget字符输入)(struct C_Widget* self, const int8 c, uint8 flag);
typedef bool(*fp_Widget全局按键按下)(const S_键盘& ks);

typedef struct C_Widget* (*fp_WidgetCall_Create)(S_UI渲染环境* ctx);
typedef void(*fp_WidgetCall_CreateWidget)(S_UI渲染环境& ctx, C_Widget* self);
typedef uint32(*fp_项层级计算)(S_Object* item, int32 缩减, int32& 行开始偏移, C_Widget** w, uint32 num, uint32& index);

typedef void(*fp_Widget变换)(struct C_Widget* self);

typedef bool(*fp_文件处理回调)(C_Widget* self, const std::vector<std::u16string>& name, E_对话框类型 方式);
typedef bool(*fp_打开关闭)(C_Widget* self, bool show);

typedef void(*fp_Widget文本输入回调)(struct C_Widget* r, wchar_t 前, wchar_t 中, wchar_t 后);
typedef void(*fp_Widget文本回调)(struct C_Widget* r, const std::u16string& text, E_字符输入类型 输入类型);
typedef void(*fp_WidgetU8回调)(struct C_Widget* r, uint8 e);

typedef bool(*fp_Widget宽字符回调)(struct C_Widget* r, wchar_t text);
typedef void(*fp_Widget布尔值回调)(struct C_Widget* self, bool value);
typedef void(*fp_Widget绘制调整回调)(struct C_Widget* r, uint32 调整部分);

typedef struct C_Widget* (*fp_Widget添加回调)(struct C_Widget* r, uint32 当前同级组件数量);

typedef bool(*fp_列表项选中回调_str)(C_Widget* self, const std::vector<std::u16string>& name);



typedef struct {
	E_键位映射类型		m_Type;
	fp_Widget快捷键事件	event;
	struct C_Widget*	发生组件;
	E_键位执行状态		状态;

	uint8 键盘按键[4];
	uint8 键盘状态[4];
	uint8 记录;
	
	uint8 连续;
}S_键盘键位映射;

typedef struct {
	E_键位映射类型		m_Type;
	fp_Widget快捷键事件	event;
	struct C_Widget*	发生组件;
	E_键位执行状态		状态;

	uint8 键盘按键[4];
	uint8 键盘状态[4];
	uint8 鼠标按键[4];
	uint8 鼠标状态[4];
	uint8 记录;
	
	E_键位操作类型		操作类型;
}S_鼠标键位映射;

typedef struct {
	E_键位映射类型		m_Type;
	fp_Widget快捷键事件	event;
	struct C_Widget*	发生组件;
	E_键位执行状态		状态;

	uint8 键盘按键[4];
	uint8 键盘状态[4];
	uint8 鼠标按键[4];
	uint8 鼠标状态[4];

	uint8 记录;
	
	E_拖放状态 拖放状态;
}S_拖拽键位映射;

typedef struct {
	E_键位映射类型		m_Type;
	fp_Widget快捷键事件	event;
	struct C_Widget*	发生组件;
	E_键位执行状态		状态;

	uint8 键盘按键[4];
	uint8 键盘状态[4];
	uint8 鼠标按键[4];
	uint8 鼠标状态[4];

	uint8 记录;
	
	clock_t 开始计时;
	clock_t 结束计时;
}S_鼠标双击键位映射;


Inline S_鼠标键位映射* f_widget_init_鼠标键位映射() { 
	S_鼠标键位映射* km = (S_鼠标键位映射*)malloc(sizeof(S_鼠标键位映射));
	(*km) = { E_键位映射类型::e_键映射类型_鼠标, nullptr, nullptr, {},{},{},{},0, 0 };
	return km;
}
Inline S_鼠标双击键位映射* f_widget_alloc_鼠标双击键位映射() {
	S_鼠标双击键位映射* km = (S_鼠标双击键位映射*)malloc(sizeof(S_鼠标双击键位映射));
	(*km) = { E_键位映射类型::e_键映射类型_双击, nullptr, nullptr, {},{},{},{},0, 0, 0, 0 };
	return km;
}
Inline S_拖拽键位映射* f_widget_init_拖放键位映射() { 
	S_拖拽键位映射* km = (S_拖拽键位映射*)malloc(sizeof(S_拖拽键位映射));
	(*km) = { E_键位映射类型::e_键映射类型_拖放, nullptr, nullptr, {},{},{},{},0, 0 };
	return km;
}
Inline S_键盘键位映射* f_widget_init_键盘位映射() {
	S_键盘键位映射* km = (S_键盘键位映射*)malloc(sizeof(S_键盘键位映射));
	(*km) = { E_键位映射类型::e_键映射类型_键盘, nullptr, nullptr, {},{}, 0, false };
	return km;
}
Inline S_拖拽键位映射* f_widget_init_拖拽键位映射() { 
	S_拖拽键位映射* km = (S_拖拽键位映射*)malloc(sizeof(S_拖拽键位映射));
	(*km) = { E_键位映射类型::e_键映射类型_拖拽, nullptr, nullptr, {},{},{},{},0, 0 };
	return km;
}


typedef void(*fp_Layout)(struct C_Widget* self, struct C_Widget** ws, uint32 num);
struct S_布局器 {
	std::vector<S_布局器*>	m_子部件;
	//fp_Layout				mf_Layout;
	virtual void f_poll(struct C_Widget** ws, uint32 num) = 0;
};

typedef struct {
	struct C_Widget**	m_W;
	uint32				m_Num;
}S_需更新部件;
typedef S_需更新部件(*fp_getUpdateWidget)(struct C_Widget* self);

typedef struct {
	uint32	m_Type;
	void*	m_Next;
}S_拖放数据;
typedef E_事件是否传递(*fp_Widget拖放)(struct C_Widget* self, const S_鼠标& 鼠标, S_拖放数据& data);
typedef bool(*fp_Widget结束拖放)(struct C_Widget* self, struct C_Widget* 拾取的部件, S_拖放数据& data);





struct S_纹理组添加参数 {
	std::string m_GroupName;
	std::string m_Path;
};

typedef struct {
	uint16 m_元素开始索引;
	uint16 m_元素结束索引;

	uint32 m_实例开始索引;
	uint32 m_实例结束索引;
}S_绘制更新区间;

typedef struct {
	vec2	m_中心;
	vec2	m_比例;
	vec2	m_缩放后边界;
	vec2	m_大小;
	vec2	m_偏移比例;
}S_View属性;

typedef struct {
	uvec3	m_Dim;
	S_纹理*	m_Tex;
	uint8*	m_Data;
}S_纹理填充列队;

typedef struct {
	struct C_Widget*	m_rW;
	struct C_Widget*	m_aW;
	int32				m_Loc;
}S_部件添加列队;

typedef struct {
	struct C_Widget* m_W;
}S_关联组件;

struct S_树形框数据添加池 {
	S_Object*									m_root;
	std::map<S_Object*, std::set<C_Widget*>>	m_items;
};

struct ui_绘制模板 {
	enum E_绘制模板类型 : uint8 {
		e_画预设图形,
		e_画图标,
		e_画行文本,
	};
	E_绘制模板类型 m_模板类型;
	ui_绘制模板() : m_模板类型(E_绘制模板类型::e_画预设图形) {}
};

struct C_Widget {
	fp_Widget绘制		mf_绘制;
	fp_Widget布局		mf_布局;
	fp_Widget变换		mf_变换;
	fp_Widget动画		mf_动画;
	
	fp_getUpdateWidget	mf_get更新组件;


	fp_Widget鼠标按键	mf_鼠标按键按下;
	fp_Widget鼠标按键	mf_鼠标按键放开;
	fp_Widget鼠标按键	mf_鼠标点击;
	fp_Widget鼠标按键	mf_鼠标按键双击;
	fp_Widget鼠标		mf_鼠标滚轮;
	fp_Widget鼠标移动	mf_鼠标移动;
	fp_Widget拖放		mf_拖拽;
	fp_Widget拖放		mf_开始拖拽;
	fp_Widget结束拖放	mf_结束拖拽;

	fp_Widget鼠标		mf_鼠标进入;
	fp_Widget鼠标		mf_鼠标离开;
	fp_Widget文本回调	mf_行文本输入;
	fp_Widget字符输入	mf_按键字符输入;
	fp_Widget按键按下	mf_键盘按键敲击;
	fp_文件处理回调	    mf_文件处理回调;
	
	//废弃
	fp_Widget绘制调整回调	mf_当前部件属性修改;	
	fp_打开关闭				mf_打开关闭;

	void*	m_UserData;
	S_Props m_自定义属性;

	C_Widget(S_UI渲染环境* ctx = 0);
	virtual ~C_Widget();


	virtual void f_setPos(vec2 pos);
	virtual void f_setSize(vec2 size);
	virtual void f_setMinSize(vec2 size);
	
	void f_setOriginalPos(vec2 pos);
	void f_setOriginalSize(vec2 size);

	void f_setX(float32 x);
	void f_setY(float32 y);
	void f_setW(float32 w);
	void f_setH(float32 h);


	vec2 f_getPos() const;
	vec2 f_getSize() const;
	vec2 f_getOriginalPos() const;
	vec2 f_getOriginalSize() const;
	S_Rect2Df f_getRect(bool 偏移 = false) { return {偏移 ? m_Pos : vec2{}, m_Size}; }

	struct C_Widget管理* f_get窗口管理();


	uint32			f_get子部件数量() { return uint32(m_子组件.size()); }
	S_需更新部件	f_get更新组件();
	C_Widget*		f_get子组件(uint32 id);

	void f_裁剪();
	void f_绘图();

	virtual void f_添加子组件(C_Widget* w, int32 loc = -1);
	virtual void f_销毁子组件(int32 id);
	virtual void f_bind属性(S_Props& p) { m_自定义属性 = p; m_Type = p.m_Type; };
	virtual void f_属性更新到组件(){}


	void	f_替换子组件(int32 id, C_Widget* w);
	void	f_置裁剪(bool 裁剪);
	void	f_置显示(bool 显示);
	void	f_标记为引用画布() { m_引用画布 = true; }
	//void	f_标记区域更新() { m_更新绘制属性 = true; }
	void	f_绑定窗口管理(C_Widget管理* gm);
	void	f_添加画布(S_2D画布* 引用画布 = nullptr);
	void	f_移除画布();
	//void	f_置子组件绘制根区域为当前组件();
	

	S_UI渲染环境*	m_UIctx;
	C_Widget*		m_区域帧缓存根;
	C_Widget*		m_区域链接根;
	S_2D画布*		m_画布;
	uint32			m_渲染层;
	//uint32			m_层级ID;
	uint32			m_实例ID;
	int32			m_窗口层;
	bool			m_更新下层绘制;


	uint64			m_Type;
	std::u16string	m_WName;
	std::string		m_TypeName;
	std::u16string	m_ICO;
	S_GPU内存块*	m_图元形状;
	float32			m_图标大小;

	vec2		m_Pos;
	vec2		m_Size;
	vec2		m_Scale;
	vec2		m_MinSize;
	vec2		m_GlobalLoc;
	vec2		m_GlobalScale;

	vec2		m_文本对齐偏移;


	bool		m_开启渲染;
	bool		m_被裁剪;
	bool		m_显示;
	bool		m_拾取;
	bool		m_更新绘制属性;
	bool		m_使用父组件裁剪;

	float32		m_延申比;
	bvec2		m_是否延展;
	int8		m_间隔宽度;
	E_布局方式  m_布局方式;
	bool		m_绘制标题;
	bool		m_拖放阻止鼠标进出事件;
	bool		m_强制焦点;

	S_RGBA8UI	m_颜色A;
	S_RGBA8UI	m_颜色B;
	S_RGBA8UI	m_颜色C;
	S_2D颜色包	m_ColorA;



	static E_鼠标样式				g_鼠标样式;
	static S_鼠标					g_鼠标;
	static S_键盘					g_键盘;

	static bool						g_是否打开了弹出窗口;
	static std::set<S_键位映射*>	g_键位映射容器;


	//================ 扩展属性 =================
	S_View属性* m_扩展视口属性;


	//================= 注册按键表 =====================
	std::vector<S_键位映射*>	m_键位映射;

	std::vector<C_Widget*>	m_子组件;
	C_Widget*				m_父部件;
	vec4					m_裁剪大小;



	S_Props_UI* m_PropUILink;

	operator S_设备环境& () {
		return m_UIctx->m_Ctx;
	}

	//废弃
	S_关联组件* m_关联组件;
	std::vector<ui_绘制模板*> m_绘图模板;


protected:
	C_Widget管理*	m_GM;

	vec2	m_OriginalPos;
	vec2	m_OriginalSize;

private:
	//vec2	m_绘制区域;
	//__m128	m_Pos;
	//__m128	m_area;
	//vec4		m_裁剪Area;
	bool			m_引用画布;
	
};





typedef void(*fp_Widget文本输入完成)(C_Widget* self);

class C_文本框 : public C_Widget {

protected:
	S_文档文本		m_内部文档;

public:
	C_文本框(S_UI渲染环境& ctx, std::u16string 字体名称);
	~C_文本框();

	uint16	m_行距;
	uint16	m_字间距;
	float32	m_字号;

	S_文档文本*		m_文档;
	std::u16string	m_Text;

	vec2			m_文字边间距;
	//未处理先后循序
	S_文本选框区域ID	m_选取;
	ivec2				m_光标坐标索引;

	bool			m_开启编辑;
	bool			m_选择开启;
	E_对齐方式		m_对齐方式;
	S_矢量字体*		m_字体;


	static uvec2		g选择文本ID区间;
	static vec2			g光标绘制位置;
	
	fp_Widget文本回调		mf_行输入回调;
	fp_Widget文本回调		mf_文本输入;
	fp_Widget文本回调		mf_光标改变回调;
	
	fp_Widget宽字符回调		mf_文本过滤;
	fp_Widget文本输入完成	mf_文本完成;
	fp_Widget宽字符回调		mf_字符输入回调;

	fp_Widget更新	mf_框选时回调;
	fp_Widget更新	mf_框选后回调;

	virtual void	f_开启输入();
	virtual void	f_输入完成();

	void	f_填充文本(const std::u16string& text);
	


	S_文本前后	f_get当前输入前后字符();
	wchar_t		f_get行头字符(int32 行);
	wchar_t		f_get行尾字符(int32 行);
	uint32		f_get同样字符数量(int32 行, int32 offset, wchar_t txt);



	virtual void	f_插入字符(wchar_t t, ivec2 pos) {}
	virtual void	f_删除字符(ivec2 pos) {}
	virtual int32	f_删除选择字符() { return 0; }
	virtual void	f_清除字符() {}
	virtual void	f_插入行(uint32 pos) {}
	virtual void	f_删除行(uint32 pos) {}
	virtual void	f_置光标索引() {}
	virtual void	f_插入文本(const std::vector<std::u16string>& texts) {}
	virtual void	f_拷贝() {}
	virtual void	f_剪切() {}
	virtual void	f_set对齐偏移();
	virtual vec2	f_set光标绘制坐标(float32 行高);

};



typedef bool(*fp_部件更新阶段回调)();

struct S_UI渲染区域 {
	std::list<C_Widget*>	m_渲染组件;

	uint32		m_所属层;
	
	bool		m_重排序 = true;
	
	S_UI渲染区域();
	~S_UI渲染区域();

	void f_设置层分辨率(S_设备环境& ctx, uvec2 分辨率, uvec2 模糊纹理分辨率);
};

struct S_UI渲染层 {
	
	std::map<C_Widget*, S_UI渲染区域>	m_渲染区域;

	S_Frame2D*	m_sruface;
	S_纹理*		m_叠加纹理;
	S_纹理*		m_模糊纹理;
				
	uint32		m_帧累计;
	bool		m_顶层;
	bool		m_更新;

	S_Surface2D* m_合成层;

	S_UI渲染层(S_UI渲染环境& uiCtx, uvec2 纹理大小);
	~S_UI渲染层();

	bool f_添加绘制区域(C_Widget* key, C_Widget* w);
	bool f_移除绘制区域(C_Widget* key, C_Widget* w);
	void f_替换绘制区域(C_Widget* key, C_Widget* w, C_Widget* 原组件);
	void f_清除绘制组件();
	void f_设置层分辨率(S_设备环境& ctx, uvec2 分辨率, uvec2 模糊纹理分辨率);


	void f_插入绘制组件(C_Widget* key, C_Widget* w, C_Widget* 上层组件);

};


struct C_Widget管理 {
	S_UI渲染环境*	m_UICtx;
	C_Widget*		m_Root;
	
	S_Window*			m_Window;
	S_WindowSurface*	m_渲染面;

	C_Widget*			m_当前拖拽部件;
	C_Widget*			m_当前操作部件;
	
	S_拖放数据			m_拖放数据;

	C_Widget*	gTopWidget[64]	= {};
	uint8		gTopWidgetCount	= 0;

	C_Widget*	gHoverWidget[64]	= {};
	uint8		gHoverWidgetCount	= 0;

	int8		m_弹出层组件拾取计数;
	int8		m_悬浮层组件拾取计数;
	int8		m_下层组件拾取计数;
	
	S_板载缓存*	m_投影矩阵;
	S_板载缓存*	m_采样属性;
	
	
	
	
	S_Viewport	视口;
	S_Rect2D	裁剪;
	vec2		窗口桌面位置;
	uvec2		m_模糊纹理大小;

	S_纹理集*	m_合成写入纹理集;
	S_纹理集*	m_合成采样纹理集;
	
	S_纹理集*	m_模糊写入纹理集;
	S_纹理集*	m_模糊采样纹理集;

	uint32							m_顶层渲染层;
	std::vector<S_UI渲染层*>		m_帧渲染层;
	S_FrameSample_TAA				m_帧采样属性[DEF_UI_LayerNum];
	

	S_GPU纹理参数槽				m_合成纹理绑定槽;
	S_GPU计算*					m_图层累积;
	S_GPU计算*					m_图层模糊;
	C_DescriptorSet*			m_DS_累积;
	C_DescriptorSet*			m_DS_模糊;
	
	S_推送常量					m_合成常量参数;

	



	uint8 鼠标按键状态[8];
	uint8 拖放状态;

	bool 执行鼠标点击;
	bool 是否执行UI部件事件;
	bool 键盘按键向下传递;

	bool 鼠标左键按下传递;
	bool 鼠标左键放开传递;
	bool 鼠标右键按下传递;
	bool 鼠标右键放开传递;
	bool 鼠标中键按下传递;
	bool 鼠标中键放开传递;

	bool 有输入事件;

	

	std::vector<C_Widget*>			m_根部件切换组;
	std::vector<S_纹理填充列队>		m_纹理填充列队;
	C_Widget*						m_上一次焦点组件[128];
	int16							m_上一次焦点组件数量;
	C_Widget*						m_焦点组件[128];
	int8							m_焦点数量;
	C_文本框*						m_当前独占操作文本框;
	C_Widget*						m_当前文本输入框;

	fp_部件更新阶段回调				mf_输入执行前回调;
	fp_部件更新阶段回调				mf_输入执行后回调;



	static std::vector<std::u16string>	m_拖放文件名;
	

	//废弃
	S_渲染参数		m_渲染参数;

	C_Widget管理(S_UI渲染环境& Ctx);
	~C_Widget管理();

	void f_重置事件();


	uint32	f_添加渲染层(uint32 绘图层, C_Widget* key);
	void	f_移除渲染层(uint32 绘图层, C_Widget* key);
	void	f_替换绘制层(uint32 绘图层, C_Widget* key, C_Widget* 原组件);
	void	f_插入绘制层(uint32 绘图层, C_Widget* key, C_Widget* 上层组件);

	void f_裁剪层(uint32 开始层);
	void f_记录裁剪层(uint32 开始层);
	void f_裁剪层();
	void f_更新层(uint32 层);
	void f_刷新置层(uint32 层);

	void f_设置渲染层大小(uvec2 分辨率);
	void f_绘制子组件(C_Widget* data);
	

	void f_绘制编辑框文本编辑();
	void f_绑定绘制编辑框(C_Widget* w);
	void f_解绑编辑框绘制(C_Widget* w);


	S_TexArrayRes*	f_加载图标(std::string 组名称, std::string path);
	
private:
	
	std::vector<S_UI渲染层*>	m_渲染层垃圾回收;
	std::vector<S_纹理*>		m_叠加纹理垃圾回收;
	//std::vector<C_Widget*>		m_渲染区域根;

	std::set<uint32>			m_异步裁剪层记录;

	S_2D画布*					m_文本编辑框画布;

};



C_Widget管理* f_ui_当前窗口管理();


class C_渲染层分配 {
	uint32			m_层ID;
	C_Widget管理*	m_GM;
public:
	C_渲染层分配(uint32 layer);

	C_渲染层分配 f_下一层();

	operator uint32 () const {
		return m_层ID;
	}

	C_渲染层分配(const C_渲染层分配&) = delete;
	C_渲染层分配& operator=(const C_渲染层分配&) = delete;

	C_渲染层分配(C_渲染层分配&&) = default;
	C_渲染层分配& operator = (C_渲染层分配&&) = default;

	void f_置组件渲染层(C_Widget* w);
	void f_移除渲染层组件(C_Widget* w);
	void f_替换渲染层组件(C_Widget* w, C_Widget* old);

};




class C_项面板项 : public C_Widget {
public:
	S_列表填充数据		m_项;
	fp_列表项选中回调	m_项选中回调;

	C_项面板项(S_UI渲染环境& ctx) : C_Widget(&ctx), m_项选中回调(nullptr) {
		m_项 = {};
	}
	//~C_弹出面板项() {}
};

typedef struct {
	uint32 m_语言类型;

}S_语言;



void f_widget_裁剪组件(const vec2& pos, const vec4& 裁剪area, C_Widget* w);
void f_widget_裁剪组件_avx(const vec2& pos, const vec4& area, C_Widget** ws, uint8 num=8);
void f_widget_单个部件裁剪(C_Widget* w, const vec4& 父area, const vec2& 父全局坐标);
int8 f_widget_筛选焦点组件_avx(C_Widget** ws, uint8 num, const vec2& point);

bool f_widget_点是否在组件内(C_Widget* w, const vec2& point);
//bool f_widget_点是否在组件内(C_Widget* w);


void f_widget_销毁子部件(C_Widget* self, int32 offset, int32 num, bool 即时销毁);
void f_widget_remove区间子组件(C_Widget* self, int32 s, int32 e = -1, bool 即时销毁=true);
void f_widget_remove子部件(C_Widget* self, uint32* id, uint32 num, bool 即时销毁 = true);
void f_widget_remove子部件(C_Widget* self, std::vector<C_Widget*>& ws, bool 即时销毁=true);
void f_widget_remove所有子部件(C_Widget* self, bool 即时销毁=true);

void f_widget_push待销毁部件(C_Widget** ws, uint32 num);


void f_widget_push待添加部件(C_Widget* r, C_Widget** ws, uint32 num, int32 offset, bool 即时执行 = false);
void f_widget_push待添加部件(C_Widget* r, C_Widget* ws, int32 loc, bool 即时执行 = false);
void f_widget_执行待添加部件();

void f_widget_添加子组件(C_Widget* self, const std::vector<C_Widget*>& ws);
void f_widget_set子组件(C_Widget* self, C_Widget* s, int32 loc);

void f_widget_关联组件(C_Widget* r, C_Widget* s);
void f_widget_clear焦点组件();

uint32	f_widget_取组件位置索引(C_Widget* self, C_Widget* 要查找的组件);
void	f_widget_移动层(C_Widget* self, uint32 源组件位置索引, uint32 目标位置索引);


void f_widget_更新渲染层(C_Widget* self);
void f_widget_重构渲染层(C_Widget* self);


Inline void f_widget_添加绘制画布(C_Widget* self, S_2D画布* 引用画布 = nullptr) {
	self->f_添加画布(引用画布);
}

Inline void f_widget_更新绘制(C_Widget* self) {
	self->m_更新绘制属性 = true;
	f_widget_更新渲染层(self);
}

Inline S_Surface2D* f_widget_get渲染层(C_Widget* self, uint32 loc) {
	return self->m_画布->m_绘制元素[loc];
}

Inline S_Rect2D f_widget_get裁剪(C_Widget* self) {
	S_Rect2D 裁剪;
	裁剪.offset.x = self->m_裁剪大小.x;
	裁剪.offset.y = self->m_裁剪大小.y;
	裁剪.extent.x = (self->m_裁剪大小.z - self->m_裁剪大小.x);
	裁剪.extent.y = (self->m_裁剪大小.w - self->m_裁剪大小.y);
	return 裁剪;
}

Inline vec4 f_widget_区域合并(vec4 rect, C_Widget* self) {
	return {
		min(rect.x, self->m_裁剪大小.x), min(rect.y, self->m_裁剪大小.y),
		max(rect.z, self->m_裁剪大小.z), max(rect.w, self->m_裁剪大小.w),
	};
}

Inline S_Rect2D f_widget_裁剪转区域(vec4 rect) {
	return {
		{ int32(rect.x), int32(rect.y)},
		{ uint32(rect.z - rect.x), uint32(rect.w - rect.y)}
	};
}

void f_widget_set绘制根区域组件(C_Widget* self, C_Widget* w);
void f_widget_加入顶层绘图(C_Widget* self);


/****************************************************************
*           顶层窗口
*****************************************************************/

//弹出顶层窗口
uint8			f_widget_top_push(C_Widget管理* gm, C_Widget* w);
uint8			f_widget_top_push(C_Widget* w, uint8 offset);
uint8			f_widget_top_close(C_Widget管理* gm);
uint8			f_widget_顶层窗口_pop(C_Widget管理* gm, uint8 num);
S_需更新部件	f_widget_getTop(C_Widget管理* gm);
C_Widget*		f_widget_getBack(C_Widget管理* gm);
uint8			f_widget_getTopNum(C_Widget管理* gm);




/****************************************************************
*           悬停窗口
*****************************************************************/
uint8		f_widget_hover_push(C_Widget管理* gm, C_Widget* w);
uint8		f_widget_hover_pop(C_Widget管理* gm, uint8 offset);
uint8		f_widget_hover_close(C_Widget管理* gm);
C_Widget*	f_widget_hover_get(C_Widget管理* gm, uint32 index = 0);





//void f_裁剪(__m128& area);
#define f_widget_get鼠标局部位置(pos, w) ( pos - ((w)->m_GlobalLoc) )
#define f_widget_转换坐标到原始坐标(pos, w) ( (pos) / ((w)->m_Scale.x) )

Inline vec2 f_widget_get鼠标位置(C_Widget* self) {
	return f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self);
}

#define 部件画布(w) (w).m_画布







/****************************************************************
*						 扩展属性预设
*****************************************************************/
inline void f_Widget_计算偏移比例(C_Widget* self) {
	vec2 一半大小 = vec_mul(self->m_Size, 0.5f);

	self->m_扩展视口属性->m_大小 = self->m_Size;
	float32 左边距离 = (self->m_扩展视口属性->m_中心.x);
	float32 顶边距离 = (self->m_扩展视口属性->m_中心.y);
	self->m_扩展视口属性->m_偏移比例.x = 左边距离 / self->m_Size.x;
	self->m_扩展视口属性->m_偏移比例.y = 顶边距离 / self->m_Size.y;
}

inline void f_widget_开启视口属性(C_Widget* self) {
	self->m_扩展视口属性 = (S_View属性*)malloc(sizeof(S_View属性));
	*(self->m_扩展视口属性) = { {}, {1,1}, {2048,2048}, {2048,2048}, {0.5f, 0.5f} };
	//f_Widget_计算偏移比例(self);
	self->m_扩展视口属性->m_大小 = self->m_Size;
}



void f_Widget_鼠标位置视口缩放(C_Widget* self, const vec2& 缩放量);

inline void f_C_Widget_鼠标位置视口缩放(C_Widget* self, const vec2& 缩放量) {
	auto 鼠标局部位置 = f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self);
	鼠标局部位置 = 鼠标局部位置 - self->m_扩展视口属性->m_中心;
	auto 比例 = 鼠标局部位置 / self->m_扩展视口属性->m_缩放后边界;
	//std::cout<<"缩放量 = "<< 缩放量.x << std::endl;

	self->m_扩展视口属性->m_比例 = self->m_扩展视口属性->m_比例 * 缩放量;

	if(self->m_扩展视口属性->m_比例.x < 0.00001) self->m_扩展视口属性->m_比例.x = 0.00001;
	if(self->m_扩展视口属性->m_比例.y < 0.00001) self->m_扩展视口属性->m_比例.y = 0.00001;

	if(self->m_扩展视口属性->m_比例.x > 100000) self->m_扩展视口属性->m_比例.x = 100000;
	if(self->m_扩展视口属性->m_比例.y > 100000) self->m_扩展视口属性->m_比例.y = 100000;


	vec2 新久边界差 = self->m_扩展视口属性->m_缩放后边界;
	self->m_扩展视口属性->m_缩放后边界 = self->m_扩展视口属性->m_大小 * self->m_扩展视口属性->m_比例;
	新久边界差 = self->m_扩展视口属性->m_缩放后边界 - 新久边界差;

	self->m_扩展视口属性->m_中心 = self->m_扩展视口属性->m_中心 - (新久边界差 * 比例);
	
	f_Widget_计算偏移比例(self);
	self->m_更新绘制属性 = true;
}

Inline void f_C_Widget_鼠标位置视口缩放(C_Widget* self) {
	auto 鼠标局部位置 = f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self);
	鼠标局部位置 = 鼠标局部位置 - self->m_扩展视口属性->m_中心;
	auto 比例 = 鼠标局部位置 / self->m_扩展视口属性->m_缩放后边界;
	//std::cout<<"缩放量 = "<< 缩放量.x << std::endl;

	vec2 新久边界差 = self->m_扩展视口属性->m_缩放后边界;
	self->m_扩展视口属性->m_缩放后边界 = self->m_扩展视口属性->m_大小 * self->m_扩展视口属性->m_比例;
	新久边界差 = self->m_扩展视口属性->m_缩放后边界 - 新久边界差;

	self->m_扩展视口属性->m_中心 = self->m_扩展视口属性->m_中心 - (新久边界差 * 比例);
	//self->m_扩展视口属性->m_边界 = 新边界;

	f_Widget_计算偏移比例(self);
	self->m_更新绘制属性 = true;
}

void f_Widget_保持偏移比例(C_Widget* pw, C_Widget* self, uint32 方向位域 = E_方向位域::e_横向位域 | E_方向位域::e_纵向位域);
EngineAPI_EXPORT void f_Widget_视口偏移(C_Widget* self, float32 x, float32 y);

inline vec2 f_Widget_getOriginal(const vec2& value, const vec2& scale) {
	return value / scale;
}

inline void f_Widget_应用视口缩放(C_Widget* self, C_Widget* view) {
	view->f_setSize(self->m_Size);
	view->m_Scale = self->m_扩展视口属性->m_比例;
}

Inline void f_Widget_鼠标位置视口缩放(C_Widget* self, const vec2& 鼠标位置, const vec2& 步进) {
	self->m_扩展视口属性->m_比例.x *= 步进.x;
	self->m_扩展视口属性->m_比例.y *= 步进.y;

	self->m_Scale = self->m_扩展视口属性->m_比例;
}

inline void f_Widget_应用视口移动(C_Widget* self) {
	//view->f_setLoc(view->f_getOriginalPos() * self->m_扩展视口属性->m_比例 + self->m_扩展视口属性->m_中心);
	self->m_更新绘制属性 = true;
}

//时间  不是时间线坐标
Inline float32 f_widget_从鼠标位置计算时间帧(C_Widget* self, float32 时间区间缩放) {
	auto c = f_widget_get鼠标局部位置(self->g_鼠标.gPos, self);
	int32 当前帧 = ((c.x - self->m_扩展视口属性->m_中心.x)) / self->m_扩展视口属性->m_比例.x / 时间区间缩放;
	return 当前帧;
}

EngineAPI_EXPORT void f_widget_构建滚动行组件(C_Widget* self, float32 行高度);

EngineAPI_EXPORT void f_Widget_应用视口滚动(C_Widget* self, C_Widget* view, E_方向 方向);
EngineAPI_EXPORT void f_Widget_限定视口滚动(C_Widget* self, float32 父组件大小, float32* view, E_方向 方向, float32 s);
EngineAPI_EXPORT void f_widget_移除组件链接(C_Widget* self);
EngineAPI_EXPORT void f_widget_移除组件链接(std::vector<C_Widget*>& ws);

EngineAPI_EXPORT void f_widget_属性链接组件(S_Props& prop, const std::vector<C_Widget*>& ws);
EngineAPI_EXPORT void f_widget_属性断开组件(S_Props& prop, const std::vector<C_Widget*>& ws);
EngineAPI_EXPORT void f_widget_解绑属性(C_Widget* self, S_Props& prop);
EngineAPI_EXPORT void f_widget_绑定属性(C_Widget* self, S_Props& prop);


typedef struct {
	vec2 选框左边右边;
	uvec2 选中文本区间;
}S_文本选框;


//返回光标在鼠标后位置  鼠标在字符1位置 返回0
vec2	f_widget_取鼠标在后光标位置(C_文本框* self, const vec2& 鼠标位置, E_对齐方式 对齐方式, vec2 offset, const std::u16string& text);
//返回光标在鼠标后位置  鼠标在字符0位置 返回1
int32	f_widget_从鼠标取光标索引(C_文本框* self, const vec2& 鼠标位置, E_对齐方式 对齐方式, std::u16string text, float32 行高度);
//S_文本选框	f_widget_选择编辑文本(C_文本框* self, const vec2& 光标位置);
void	f_widget_选择编辑文本(C_文本框* self, const uvec2& 区间);
uint16	f_ui_编辑文本(C_Widget* self, uint16 光标位置, const S_输入环境& input, E_对齐方式 对齐方式, vec2 offset, std::u16string& text);






//void f_ui_set鼠标样式(E_鼠标样式 样式);
void			f_widget_开始输入法();
void			f_widget_结束输入法();
void			f_widget_结束输入状态();
bool			f_widget_输入法是否有输入();
ivec2			f_widget_get输入法窗口位置();
void			f_widget_发射输入法文本(const std::u16string& str);
void			f_widget_set输入法窗口位置(const ivec2& pos);
std::u16string	f_widget_get输入法文本();
bool			f_widget_是否处在输入法状态();
void			f_widget_set当前正在输入的文本(const std::wstring& txt);
//void			f_widget_拷贝文本();



void		f_widget_set当前窗口矩形(const vec4& 区域);
vec4		f_widget_get当前窗口矩形();

void		f_widget_交换顶层组件(C_Widget管理* gm, uint32 新顶层组件ID);
void		f_widget_交换顶层组件(C_Widget* w, uint32 新顶层组件ID);

Inline vec2 f_widget_限制组件大小(C_Widget* self) {
	vec4 窗口大小 = f_widget_get当前窗口矩形();
	if (self->m_Size.x > 窗口大小.z - 窗口大小.x) {
		self->m_Size.x = 窗口大小.z - 窗口大小.x;
	}
	if (self->m_Size.y > 窗口大小.w - 窗口大小.y) {
		self->m_Size.y = 窗口大小.w - 窗口大小.y;
	}
	return {};
}

Inline vec2 f_widget_弹出窗口坐标矫正(C_Widget* self, vec2 pos) {
	auto e = self->f_get更新组件();
	if(e.m_Num) self->mf_布局(self, e.m_W, e.m_Num);
	//vec4 当前菜单大小 = self->m_裁剪大小;
	//vec4 窗口大小 = f_widget_get当前窗口矩形();

	if (pos.x + self->m_Size.x >= self->m_UIctx->m_GM->视口.width) {
		pos.x = self->m_UIctx->m_GM->视口.width - self->m_Size.x;
	}
	if (pos.x < 0) pos.x = 0;

	if (pos.y + self->m_Size.y >= self->m_UIctx->m_GM->视口.height) {
		pos.y = self->m_UIctx->m_GM->视口.height - self->m_Size.y;
		
	}
	if (pos.y < 0) pos.y = 0;

	return pos;
}

//uint32 f_widget_定时关闭弹出组件(void* pParam);
void f_widget_线程定时关闭弹出组件(int32 延时 = 600);
void f_widget_取消定时关闭弹出组件();

void f_widget_set鼠标位置(const vec2* pos);

void f_widget_开始固定鼠标位置();
void f_widget_固定鼠标位置();
void f_widget_结束鼠标固定();

vec2 f_widget_get鼠标步进();


void f_widget_set当前激活编辑框(C_Widget* self);


inline auto f_widget_getSurface2D = [](C_Widget* self, uint32 index) {
	assert(self->m_画布 && self->m_画布->m_绘制元素.size() > index);
	return self->m_画布->m_绘制元素[index];
};



inline uint32 f_widget_UI层属性(uint8 层ID, uint8 层数量) {
	return uint32(层ID) | (uint32(层数量) << 8);
}

inline uint32 f_widget_UI层区域(uvec2 帧偏移) {
	return (帧偏移.x) | ((帧偏移.y) << 16);
}


inline uint32 f_widget_UI层采样属性(uint8 帧累积, uint8 层区域属性偏移, uint8 层绘制区域数量) {
	return uint32(帧累积) | (uint32(层区域属性偏移) << 8) | (uint32(层绘制区域数量) << 16) ;
}

inline void f_widget_UI层区域属性(S_FrameSample_TAA& fs, vec4 裁剪, bool 更新, uint8 调试) {
	
	fs.m_LayerArea_Offset = f_widget_UI层区域(_uVec2(裁剪.x, 裁剪.y));
	fs.m_LayerArea_Size = f_widget_UI层区域(_uVec2(裁剪.z, 裁剪.w));

	fs.m_LayerAttr = uint32(更新) | (uint32(调试) << 8);
}





